package com.icongyou.enterprise.talent_analysis.service;

import com.icongyou.enterprise.talent_analysis.entity.PortraitCache;
import com.icongyou.enterprise.talent_analysis.mapper.PortraitCacheMapper;
import com.icongyou.enterprise.talent_analysis.service.impl.PortraitCacheServiceImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.time.LocalDateTime;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

/**
 * 画像缓存服务测试
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("画像缓存服务测试")
class PortraitCacheServiceImplTest {

    @Mock
    private PortraitCacheMapper cacheMapper;
    
    @Mock
    private ObjectMapper objectMapper;

    @InjectMocks
    private PortraitCacheServiceImpl service;

    @BeforeEach
    void setUp() {
        // Mock对象自动注入
    }

    @Test
    @DisplayName("获取缓存 - 缓存命中")
    void testGetCache_Hit() throws Exception {
        // Arrange
        String studentId = "student-1";
        String templateId = "template-1";
        
        PortraitCache cache = createValidCache(studentId, templateId);
        
        when(cacheMapper.selectByStudentAndTemplate(studentId, templateId))
            .thenReturn(cache);
        when(objectMapper.readValue(anyString(), any(com.fasterxml.jackson.core.type.TypeReference.class)))
            .thenReturn(java.util.List.of());

        // Act
        var result = service.getFromCache(studentId, templateId);

        // Assert
        assertNotNull(result);
        verify(cacheMapper).selectByStudentAndTemplate(studentId, templateId);
    }

    @Test
    @DisplayName("获取缓存 - 缓存不存在")
    void testGetCache_Miss() {
        // Arrange
        when(cacheMapper.selectByStudentAndTemplate(anyString(), anyString()))
            .thenReturn(null);

        // Act
        var result = service.getFromCache("student-1", "template-1");

        // Assert
        assertNull(result);
    }

    @Test
    @DisplayName("异步更新缓存 - 新建缓存")
    void testAsyncUpdateCache_New() throws Exception {
        // Arrange
        String studentId = "student-1";
        String templateId = "template-1";
        var response = new com.icongyou.enterprise.talent_analysis.entity.PortraitResponse();
        response.setLabels(java.util.List.of("技术能力"));
        response.setScores(java.util.List.of(4.5));
        response.setDimensions(java.util.List.of());
        response.setAiUsed(true);
        
        when(cacheMapper.selectByStudentAndTemplate(studentId, templateId))
            .thenReturn(null);
        when(objectMapper.writeValueAsString(any())).thenReturn("[]");
        when(cacheMapper.insert(any(PortraitCache.class))).thenReturn(1);

        // Act
        service.asyncUpdateCache(studentId, templateId, response);

        // Assert
        // 异步方法,验证方法被调用即可
        Thread.sleep(100); // 等待异步执行
        verify(cacheMapper, timeout(1000)).selectByStudentAndTemplate(studentId, templateId);
    }

    @Test
    @DisplayName("异步更新缓存 - 更新现有缓存")
    void testAsyncUpdateCache_Update() throws Exception {
        // Arrange
        String studentId = "student-1";
        String templateId = "template-1";
        var response = new com.icongyou.enterprise.talent_analysis.entity.PortraitResponse();
        
        PortraitCache existing = createValidCache(studentId, templateId);
        existing.setVersion(1);
        
        when(cacheMapper.selectByStudentAndTemplate(studentId, templateId))
            .thenReturn(existing);
        when(objectMapper.writeValueAsString(any())).thenReturn("[]");
        when(cacheMapper.updateByIdWithVersion(any(PortraitCache.class)))
            .thenReturn(1);

        // Act
        service.asyncUpdateCache(studentId, templateId, response);

        // Assert
        Thread.sleep(100);
        verify(cacheMapper, timeout(1000)).updateByIdWithVersion(any(PortraitCache.class));
    }

    @Test
    @DisplayName("清除模板缓存 - 清除使用该模板的所有画像缓存")
    void testInvalidateTemplateCache() {
        // Arrange
        String templateId = "template-1";
        when(cacheMapper.deleteByTemplateId(templateId)).thenReturn(8);

        // Act
        service.invalidateTemplateCache(templateId);

        // Assert
        verify(cacheMapper).deleteByTemplateId(templateId);
    }



    // ==================== Helper Methods ====================

    private PortraitCache createValidCache(String studentId, String templateId) {
        PortraitCache cache = new PortraitCache();
        cache.setId("cache-id");
        cache.setStudentId(studentId);
        cache.setTemplateId(templateId);
        cache.setLabelsJson("[\"技术能力\"]");
        cache.setScoresJson("[4.5]");
        cache.setDimensionsJson("[]");
        cache.setAiUsed(true);
        cache.setGeneratedAt(LocalDateTime.now());
        cache.setUpdatedAt(LocalDateTime.now());
        cache.setVersion(0);
        return cache;
    }
}
